package com.hx.good.web;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.hx.common.R;
import com.hx.common.api.MiaoshaGoodsService;
import com.hx.common.api.OrderService;
import com.hx.common.common.enums.ResultStatus;
import com.hx.common.common.resultbean.ResultGeekQ;
import com.hx.common.constant.GoodServerConstant;
import com.hx.common.constant.VerifyCodeConstant;
import com.hx.common.domain.MiaoshaGoods;
import com.hx.common.domain.MiaoshaOrder;
import com.hx.common.domain.MiaoshaUser;
import com.hx.common.domain.OrderInfo;
import com.hx.common.exception.GlobleException;
import com.hx.common.to.RedisGoodsTo;
import com.hx.common.utils.VerifyCodeUtil;
import com.hx.good.feign.MiaoShaFeign;
import com.hx.common.vo.GoodsDetailVo;
import com.hx.common.vo.GoodsVo;
import org.redisson.RedissonTopic;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Author wonghiu
 * @Date 2021/6/4 19:12
 * @Version 1.0.1
 */
@Controller
@RequestMapping("/goods")
public class GoodsController {
    private static Logger logger = LoggerFactory.getLogger(GoodsController.class);
    @Autowired
    private MiaoshaGoodsService goodsService;

    @Autowired
    private MiaoShaFeign miaoShaFeign;

    @Reference(check = false)
    private OrderService orderService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping(value="/to_list")
    public String list(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user) {
        model.addAttribute("user", user);
        List<GoodsVo> goodsList = goodsService.listMiaoShaGoodsVo();

        model.addAttribute("goodsList", goodsList);

        return "goods_list";
    }

    @RequestMapping(value="/detail/{goodsId}")
    @ResponseBody
    public R detail(HttpServletRequest request, HttpServletResponse response, Model model, MiaoshaUser user,
                              @PathVariable("goodsId")long goodsId) {

        GoodsVo goods = goodsService.getMiaoShaGoodsVoByGoodsId(goodsId);

        long startAt = goods.getStartDate().getTime();
        long endAt = goods.getEndDate().getTime();
        long now = System.currentTimeMillis();
        int miaoshaStatus = 0;
        int remainSeconds = 0;
        if(now < startAt ) {//秒杀还没开始，倒计时
            miaoshaStatus = 0;
            remainSeconds = (int)((startAt - now )/1000);
        }else  if(now > endAt){//秒杀已经结束
            miaoshaStatus = 2;
            remainSeconds = -1;
        }else {//秒杀进行中
            miaoshaStatus = 1;
            remainSeconds = 0;
        }
        GoodsDetailVo vo = new GoodsDetailVo();
        System.out.println(goods);
        vo.setGoods(goods);
        vo.setUser(user);
        vo.setRemainSeconds(remainSeconds);
        vo.setMiaoshaStatus(miaoshaStatus);
        R r = new R();
        r.setData(vo);

        return r;
    }

    // 秒杀商品上架，并预设库存至缓存中
    @RequestMapping("/submit")
    @ResponseBody
    public R submit(){

        // 使用分布式锁保证上架接口的幂等性
        RLock lock = redissonClient.getLock("goods:submit_lock");
        lock.lock(10, TimeUnit.SECONDS);
        try{
            goodsService.submitGoods2Cache();
        }finally {
            lock.unlock();
        }
        return R.ok();
    }

    @PostMapping(value = "/kill")
    @ResponseBody
    public R kill(HttpServletRequest request,
                  @RequestParam("goodsId") Long goodsId,
                  @RequestParam("randomCode") String randomCode,
                  @RequestParam("verifyCode") String verifyCode){
        MiaoshaUser loginUser = (MiaoshaUser) request.getSession().getAttribute("loginUser");
        // 检查验证码
        if(!verifyCode.equals(redisTemplate.opsForValue().get(VerifyCodeConstant.VCODE_MIAOSHA_PREFIX +loginUser.getId()))){
            return R.error("验证码错误");
        }
        // 远程调用秒杀服务
        R result = miaoShaFeign.kill(goodsId,randomCode);
        return result;
    }
    @GetMapping("/check")
    @ResponseBody
    public R check(@RequestParam("orderId") Long orderId) {
        // 远程调订单服务查看订单状态
        Integer state = orderService.getOrderStateById(orderId);
        if (state==null){
            return R.error("状态查无效");
        }
        return R.ok().setData(state);
    }

    @GetMapping("/getOrderDetail")
    @ResponseBody
    public R getOrderDetail(@RequestParam("orderId") Long orderId) {
        // 远程调订单服务查看订单
        OrderInfo order = orderService.getOrderById(orderId);
        GoodsVo goods = goodsService.getGoodsVoByGoodsId(order.getGoodsId());
        if (order==null){
            return R.error("无效订单");
        }

        return R.ok().put("goods",goods).put("order",order);
    }
    @GetMapping("/getRandomCode")
    @ResponseBody
    public R getRandomCode(@RequestParam("goodsId") Long goodsId){
        String randomCode = JSON.parseObject(redisTemplate.opsForValue().get(GoodServerConstant.GOODS_INFO_PREFIX + goodsId), RedisGoodsTo.class).getRandomCode();
        if (randomCode==null){
            return R.error("随机码找不到");
        }
        return R.ok().put("randomCode",randomCode);
    }
    @RequestMapping(value = "/verifyCodeMiaosha", method = RequestMethod.GET)
    @ResponseBody
    public R getMiaoshaVerifyCode(HttpServletResponse response,HttpServletRequest request) {
        try {
            // 获取登录用户信息
            MiaoshaUser loginUser = (MiaoshaUser) request.getSession().getAttribute("loginUser");
            String verifyCode = VerifyCodeUtil.generateVerifyCode(new Random());
            BufferedImage image = VerifyCodeUtil.createVerifyCode(verifyCode);
            OutputStream out = response.getOutputStream();
            ImageIO.write(image, "JPEG", out);
            out.flush();
            out.close();
            redisTemplate.opsForValue().set(VerifyCodeConstant.VCODE_MIAOSHA_PREFIX+loginUser.getId(), String.valueOf(VerifyCodeUtil.calc(verifyCode)));
            return R.ok();
        } catch (Exception e) {
            logger.info(String.valueOf(e));
            throw new GlobleException(ResultStatus.CODE_GEN_FAIL);
        }
    }
    @RequestMapping(value = "/getgoods", method = RequestMethod.GET)
    @ResponseBody
    public R getGoodsById(@RequestParam("goodsId") Long goodsId){
        GoodsVo goodsVoByGoodsId = goodsService.getGoodsVoByGoodsId(goodsId);
        return R.ok().setData(goodsVoByGoodsId);
    }



}
